﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace KeyMap
{
    public partial class KeyMapper: Form
    {
        private static IntPtr hookId = IntPtr.Zero;
        private static LowLevelKeyboardProc proc = HookCallback;
        private static bool mappingEnabled = false;

        public KeyMapper()
        {
            InitializeComponent();
            notifyIcon1.Visible = true;
            notifyIcon1.Text = "按键映射已关闭";
        }

        private void checkBoxEnable_CheckedChanged(object sender, EventArgs e)
        {
            mappingEnabled = checkBoxEnable.Checked;
            if (mappingEnabled)
            {
                hookId = SetHook(proc);
                notifyIcon1.Text = "按键映射已启用";
            }
            else
            {
                UnhookWindowsHookEx(hookId);
                notifyIcon1.Text = "按键映射已关闭";
            }
        }

        // 托盘双击还原窗口
        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
                this.Hide();
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            UnhookWindowsHookEx(hookId);
            notifyIcon1.Dispose();
            base.OnFormClosing(e);
        }

        // Hook逻辑
        private static IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
                    GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            const int WM_KEYDOWN = 0x0100;

            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN && mappingEnabled)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                KBDLLHOOKSTRUCT hookStruct = Marshal.PtrToStructure<KBDLLHOOKSTRUCT>(lParam);

                // NumPad Enter: vkCode == 13 && flags == 0
                if (vkCode == 13 && hookStruct.flags == 1)
                {
                    SendKeys.SendWait(",");
                    return (IntPtr)1; // 拦截原键
                }
            }

            return CallNextHookEx(hookId, nCode, wParam, lParam);
        }

        private const int WH_KEYBOARD_LL = 13;

        [DllImport("user32.dll")]
        private static extern IntPtr SetWindowsHookEx(int idHook,
            LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll")]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll")]
        private static extern IntPtr CallNextHookEx(IntPtr hhk,
            int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll")]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        [StructLayout(LayoutKind.Sequential)]
        private struct KBDLLHOOKSTRUCT
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public IntPtr dwExtraInfo;
        }
    }
}
